/********************************************************************************

* @File name: ftm.h

* @Author: Pan Zhimin

* @Version: 1.0

* @Date: 2023-8-21

* @Description: FTM SA & FA TEST

******************************************************************************* */
#ifndef _FTM_H_
#define _FTM_H_

#include "zqm_module.h"
#include "zqm_app.h"
#include "hal_mcu.h"
#include "hal_adc.h"
#include "hal_uart.h"
#include "hal_disp_key.h"


/* public define */
#ifndef     bool
#define     bool                                    int8_t
#endif
#ifndef     true
#define     true                                    (1)
#endif
#ifndef     false
#define     false                                   (0)
#endif

#define     ROUND10(n)                              ((n + (n >= 0 ? 5 : -5)) / 10 * 10)

#define     OK                                      (1)
#define     FAIL                                    (2)
#define     NOT_SUPPORT                             (3)

#define     FTM_TAG                                 "\n[FTM]"
#define     FTM_LOG_ENABLE                          (true)

#if FTM_LOG_ENABLE
#define     FTM_LOG(format, ...)                    printf(FTM_TAG": %s(%d) - "format"\n",  __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define     FTM_LOG_ERR(format, ...)                printf(FTM_TAG"@error@: %s(%d) - "format"\n",  __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define     FTM_LOG(format, ...)                    do {                                                                                              \
                                                    } while (0)
#define     FTM_LOG_ERR(format, ...)                do {                                                                                              \
                                                    } while (0)
#endif

// 统一代码
#define     WDT_CLEAN()                             WdtClean()
#define     DISP_ICON(i, on)                        DispIcon(i, on)
#define     DISP_INT(i)                             DispInt(i, true, false)
#define     DISP_FLOAT(f)                           DispAsFloat(f, true)
#define     DISP_STR(s)                             DispString(s, true)
#define     DISP_REFRESH()                          DispRefresh()
#define     IS_NTC_FAULT(t)                         !IsTemValid(t)

/* 2024-06-24: mark掉的宏定义中, 由于时机问题: DrvReadKeys前面几个得到的value都是0x00, 最后一个才是0xYY, 却再也没机会转换成0xZZ了 */
//#define   READ_KEYS()                             DrvReadKeys(1)==0x04? 0x02:(DrvReadKeys(2)==0x02? 0x04:DrvReadKeys(3)) // 0x01 | (0x04 -> 0x02) | (0x02 -> 0x04)
#define     READ_KEYS()                             ({                                                                                                \
                                                        uint8_t raw = DrvReadKeys();                                                                  \
                                                        raw = raw;                                                                                    \
                                                    })

// 这里是原始的延时
#define     delay1ms(ms)                            DelayMs(ms)

// 这里是改造后的延时(超过50ms, 可以处理cat1过来的数据)
#define     DELAYms(ms)                             do {                                                                                              \
                                                          if (ms > 50) {                                                                              \
                                                              for (int i = 0; i < (ms / 10); i++, WDT_CLEAN(), delay1ms(10)) {                        \
                                                                  /* 不能处理pc uart的数据 */                                                          \
                                                                  /* 但需要处理cat1过来的数据 */                                                        \
                                                                  process_uart_cat1();                                                                \
                                                              }                                                                                       \
                                                          } else {                                                                                    \
                                                              delay1ms(ms);                                                                           \
                                                          }                                                                                           \
                                                    } while (0)

// hex_buf超长就分段: {aa bb cc ... xx yy zz}
#define     FTM_HEX_BUF_LOG(head, hex_buf, hex_len) do {                                                                                              \
                                                          char content[200] = "{ ";                                                                   \
                                                          int offset = strlen(content);                                                               \
                                                          int LEN = 0;                                                                                \
                                                          char SEP[] = "...";                                                                         \
                                                          if (strlen(head) + 2/*"{ "*/ + hex_len * 3 + 2/*"} "*/ > sizeof(content)) {                 \
                                                              LEN = (sizeof(content) - strlen(head) - 2 - 2 - strlen(SEP)) / (3 * 2);                 \
                                                          }                                                                                           \
                                                          if (LEN != 0) {                                                                             \
                                                              for (int i = 0; i < LEN; i++) {                                                         \
                                                                  sprintf(content + offset, "%02X ", (hex_buf)[i]);                                   \
                                                                  offset += strlen("2X ");                                                            \
                                                              }                                                                                       \
                                                              strcat(content, SEP);                                                                   \
                                                              offset += strlen(SEP);                                                                  \
                                                              for (int i = hex_len - LEN; i < hex_len; i++) {                                         \
                                                                  sprintf(content + offset, "%02X ", (hex_buf)[i]);                                   \
                                                                  offset += strlen("2X ");                                                            \
                                                              }                                                                                       \
                                                          } else {                                                                                    \
                                                              for (int i = 0; i < hex_len; i++) {                                                     \
                                                                  sprintf(content + offset, "%02X ", (hex_buf)[i]);                                   \
                                                                  offset += strlen("2X ");                                                            \
                                                              }                                                                                       \
                                                          }                                                                                           \
                                                          strcat(content, "}");                                                                       \
                                                          FTM_LOG("%s[%d] = %s", head, hex_len, content);                                             \
                                                    } while (0)



/* private define */
// 灯板测试, 如果需要做特殊版本, 请打开以下宏定义
//#define   FA_LED_BANK_TEST

// FA完成后是否重启 (不重启便于查看log)
#define     FA_TEST_OK_REBOOT

// SA中按5次进入Work模式(或者可用于调试数码管显示)
#define     SA_CHANGE_TO_WORK_MODE                  // 5次 不重启
#define     SA_CHANGE_TO_FA_MODE                    // 10次  重启

// FA中按5次进入Work模式(M0 & Cat1)
#define     FA_CHANGE_TO_WORK_MODE                  // 5次 不重启
#define     FA_CHANGE_TO_SA_MODE                    // 10次  重启

// SA或FA中按键切换模式 (仅M0)
#define     CHANGE_TO_XX_MODE_MO_ONLY

// SA中继电器的开与关之间的延时
#define     SA_RELAY_ON_OFF_DELAY                   (500)     // 经测试100ms亦可
// FA中多个继电器测试时之间的延时
#define     FA_RELAY_TEST_DELAY                     (1000)    // 经测试0ms亦可

// 为了兼容老项目914、959、960、961、962、963、982
#if !defined (ZQ_FUNC_DOOR1) && !defined (ZQ_FUNC_HARD_SWITCH) && !defined (ZQ_BLE_PLATFORM) && !defined (ZQ_FUNC_HUMAN) && !defined (ZQ_FUNC_POW_METER) && !defined (ZQ_COMM_PLATFORM)
/* 把新项目的各项目属性定义搬在这, 从此下面的定义就可以一致了 */
#if (CFG_DEVICE_TYPE == 914)
#define     ZQ_FUNC_DOOR1                           (1)
#define     ZQ_FUNC_HARD_SWITCH                     (1)
#define     ZQ_BLE_PLATFORM                         (0)
#define     ZQ_FUNC_HUMAN                           (0)
#define     ZQ_FUNC_POW_METER                       (0)
#define     ZQ_COMM_PLATFORM                        (8910)
#elif (CFG_DEVICE_TYPE == 959)
#define     ZQ_FUNC_DOOR1                           (1)
#define     ZQ_FUNC_HARD_SWITCH                     (1)
#define     ZQ_BLE_PLATFORM                         (8910)
#define     ZQ_FUNC_HUMAN                           (1)
#define     ZQ_FUNC_POW_METER                       (0)
#define     ZQ_COMM_PLATFORM                        (8910)
#elif (CFG_DEVICE_TYPE == 960)
#define     ZQ_FUNC_DOOR1                           (0)
#define     ZQ_FUNC_HARD_SWITCH                     (0)
#define     ZQ_BLE_PLATFORM                         (0)
#define     ZQ_FUNC_HUMAN                           (0)
#define     ZQ_FUNC_POW_METER                       (0)
#define     ZQ_COMM_PLATFORM                        (8910)
#elif (CFG_DEVICE_TYPE == 961)
#define     ZQ_FUNC_DOOR1                           (0)
#define     ZQ_FUNC_HARD_SWITCH                     (0)
#define     ZQ_BLE_PLATFORM                         (8910)
#define     ZQ_FUNC_HUMAN                           (0)
#define     ZQ_FUNC_POW_METER                       (0)
#define     ZQ_COMM_PLATFORM                        (8910)
#elif (CFG_DEVICE_TYPE == 962)
#define     ZQ_FUNC_DOOR1                           (1)
#define     ZQ_FUNC_HARD_SWITCH                     (1)
#define     ZQ_BLE_PLATFORM                         (8910)
#define     ZQ_FUNC_HUMAN                           (0)
#define     ZQ_FUNC_POW_METER                       (0)
#define     ZQ_COMM_PLATFORM                        (8910)
#elif (CFG_DEVICE_TYPE == 963)
#define     ZQ_FUNC_DOOR1                           (0)
#define     ZQ_FUNC_HARD_SWITCH                     (0)
#define     ZQ_BLE_PLATFORM                         (8910)
#define     ZQ_FUNC_HUMAN                           (0)
#define     ZQ_FUNC_POW_METER                       (0)
#define     ZQ_COMM_PLATFORM                        (8910)
#elif (CFG_DEVICE_TYPE == 982)
#define     ZQ_FUNC_DOOR1                           (1)
#define     ZQ_FUNC_HARD_SWITCH                     (1)
#define     ZQ_BLE_PLATFORM                         (8910)
#define     ZQ_FUNC_HUMAN                           (0)
#define     ZQ_FUNC_POW_METER                       (0)
#define     ZQ_COMM_PLATFORM                        (8910)
#endif
#endif

// 为了兼容老项目326
#if ((CFG_DEVICE_TYPE/100) == 24326 || CFG_DEVICE_TYPE == 212)
#ifndef ZQ_M0_MAINBOARD
#define     ZQ_M0_MAINBOARD                         (3)
#endif
#if (CFG_DEVICE_TYPE == 212)
#ifndef ZQ_COMM_PLATFORM
#define     ZQ_COMM_PLATFORM                        (582)
#endif
#endif
#endif



/****************************根据规格书里的各项目具体属性来定义***********************************/
// 继电器
/* Note: 从今(2024-05-10)开始, 不再依赖于项目类型判断有哪几个继电器, 而是最多支持3个, 失败的话由PC工具判断是否有该路继电器 */
#define     RELAY_NUM                               (3)

// 数码管
#define     HAS_LAMP                                (CFG_DEVICE_TYPE != 866)

// 按键
/* Note: 从今(2024-05-10)开始, 不再依赖于项目类型判断有哪几个按键, 而是根据KEY_NUM倒推 */
#if (CFG_DEVICE_TYPE == 866 || CFG_DEVICE_TYPE == 988)
/* 866/988: 实际没有按键, 但ZQ_KEY_NUM有值, 需重定义成0 */
#define     ZQ_KEY_NUM                              (0)
#endif

// 门开关
#define     HAS_DOOR_1                              (ZQ_FUNC_DOOR1 == 1)
#define     HAS_DOOR_2                              (false)

// 系统开关
#define     HAS_SYS                                 (ZQ_FUNC_HARD_SWITCH == 1)

// 温度传感器 (3作为LED电流检测)
#define     HAS_NTC_1                               (CFG_DEVICE_TYPE != 866)
#define     HAS_NTC_2                               (CFG_DEVICE_TYPE == 1004)
#define     HAS_NTC_3                               (false)

// 电池
#define     HAS_BATTERY                             (ZQ_FUNC_BATTERY == 1) 

// 蓝牙
#define     HAS_DEVICE_ID                           (ZQ_BLE_PLATFORM != 0)
#define     HAS_UUID                                (ZQ_BLE_PLATFORM == 582)

// 红外
#define     HAS_IRDA                                (ZQ_FUNC_HUMAN == 1)

// 功率计
#define     HAS_POWER_METER                         (ZQ_FUNC_POW_METER == 1)

// 蜂鸣器
#define     HAS_BEEP                                ((CFG_DEVICE_TYPE/100) == 24326)

// 485
#define     HAS_485_UART                            (ZQ_COMM_PLATFORM == 485)

// 对外串口
#define     HAS_COM                                 (CFG_DEVICE_TYPE == 835 || CFG_DEVICE_TYPE == 870 || CFG_DEVICE_TYPE == 915 || CFG_DEVICE_TYPE == 1198 || (CFG_DEVICE_TYPE/100) == 24326 || CFG_DEVICE_TYPE == 212 || CFG_DEVICE_TYPE == 1036)

// LED
#define     HAS_IO_LED                              (false)

// MP3 (播放3次)
#define     HAS_MP3                                 (false)
#define     MP3_NUM                                 (3)


// GPIOs
#define     GPIO_A                                  (0 << 31)               // 最高位0
#define     GPIO_B                                  (1 << 31)               // 最高位1

#define     DEBUG_TX_GPIO                           (GPIO_B | GPIO_Pin_23)  // PB23

#if HAS_BATTERY
#if (ZQ_M0_MAINBOARD == 3)
#define     BATTERY_GPIO                            (GPIO_A | GPIO_Pin_2)   // PA2
#else 
#define     BATTERY_GPIO                            (GPIO_A | GPIO_Pin_3)   // PA3
#endif
#endif

#if HAS_IRDA
#define     IRDA_GPIO                               (GPIO_A | GPIO_Pin_14)  // PA14
#endif

#if HAS_DOOR_1
#if (ZQ_M0_MAINBOARD == 3)
#define     DOOR_1_GPIO                             (GPIO_A | GPIO_Pin_1)   // PA1
#else
#define     DOOR_1_GPIO                             (GPIO_A | GPIO_Pin_2)   // PA2
#endif
#endif

#if HAS_DOOR_2
#if (ZQ_M0_MAINBOARD == 3)
#define     DOOR_2_GPIO                             (GPIO_A | GPIO_Pin_2)   // PA2
#else
#define     DOOR_2_GPIO                             (GPIO_A | GPIO_Pin_1)   // PA1
#endif
#endif

#if HAS_SYS
#define     SYS_GPIO                                (GPIO_A | GPIO_Pin_13)  // PA13
#endif

#if HAS_BEEP
#if (ZQ_M0_MAINBOARD == 3)
#define     BUZZER_GPIO                             (GPIO_A | GPIO_Pin_13)  // PA13
#else
#define     BUZZER_GPIO                             (GPIO_B | GPIO_Pin_2)   // PB2
#endif
#endif

#if HAS_IO_LED
#define     LED_1_GPIO                              (GPIO_B | GPIO_Pin_13)  // PB13 (照明)
#define     LED_2_GPIO                              (GPIO_B | GPIO_Pin_12)  // PB12 (冷凝)
#define     LED_3_GPIO                              (GPIO_B | GPIO_Pin_11)  // PB11 (蒸发)
#endif


/* 治具接线1: TP9 -> CONNECT_TO_GPIO_X; TP12 -> GND */
#if (ZQ_M0_MAINBOARD == 2)
#define     RELAY_1_GPIO                            (GPIO_B | GPIO_Pin_6)   // PB6  (MOTOR_EN)
#elif (ZQ_M0_MAINBOARD == 3) 
#define     RELAY_1_GPIO                            (GPIO_A | GPIO_Pin_3)   // PA3  (MOTOR_EN)
#else
#define     RELAY_1_GPIO                            (GPIO_B | GPIO_Pin_18)  // PB18 (MOTOR_EN)
#endif

/* 治具接线2: TP3 -> CONNECT_TO_GPIO_X; TP12 -> GND */
#if (ZQ_M0_MAINBOARD == 2)
#define     RELAY_2_GPIO                            (GPIO_B | GPIO_Pin_12)  // PB12 (FAN_EN)
#elif (ZQ_M0_MAINBOARD == 3) 
#define     RELAY_2_GPIO                            (GPIO_A | GPIO_Pin_15)  // PA15 (FAN_EN)
#else
#define     RELAY_2_GPIO                            (GPIO_B | GPIO_Pin_17)  // PB17 (FAN_EN)
#endif

/* 治具接线3: TP13 -> CONNECT_TO_GPIO_X; TP12 -> GND */
#if (ZQ_M0_MAINBOARD == 2)
#define     RELAY_3_GPIO                            (0)                     // PxNA (LIGHT_EN)
#elif (ZQ_M0_MAINBOARD == 3) 
#define     RELAY_3_GPIO                            (0)                     // PxNA (LIGHT_EN)
#else
#define     RELAY_3_GPIO                            (GPIO_A | GPIO_Pin_12)  // PA12 (LIGHT_EN)
#endif


/* 继电器(或LED)输出的N种可能 (尽量保证前面几个就能测试OK, 且不能连接到NTC或KEY的GPIO上去) */
#if (ZQ_M0_MAINBOARD == 3)
#if ((CFG_DEVICE_TYPE/100) == 24326)
#define     CONNECT_TO_GPIO_1                       (GPIO_A | GPIO_Pin_0)   // PA0  (AIO_2_IN-TP4)
#define     CONNECT_TO_GPIO_2                       (GPIO_A | GPIO_Pin_1)   // PA1  (AIO_3_IN-TP3)
#define     CONNECT_TO_GPIO_3                       (0)                     // PA6  (AIO_1_IN-TP5-NTC)
#define     CONNECT_TO_GPIO_4                       (0)                     // PB15 (TP10 - 风机)
#define     CONNECT_TO_GPIO_5                       (0)                     // PB10 (TP15 - KEY1)
#elif (CFG_DEVICE_TYPE == 212)
#define     CONNECT_TO_GPIO_1                       (GPIO_A | GPIO_Pin_0)   // PA0  (AIO_2_IN-TP4)
#define     CONNECT_TO_GPIO_2                       (GPIO_A | GPIO_Pin_6)   // PA6  (AIO_1_IN-TP5)
#define     CONNECT_TO_GPIO_3                       (0)                     // PA1  (AIO_3_IN-TP3-NTC)
#define     CONNECT_TO_GPIO_4                       (0)                     // PB15 (TP10 - 风机 - 无)
#define     CONNECT_TO_GPIO_5                       (0)                     // PB10 (TP15 - KEY1)
#else
#error "please add CFG_DEVICE_TYPE == xx"
#endif
#elif (ZQ_M0_MAINBOARD == 2)
#define     CONNECT_TO_GPIO_1                       (0)                     // PA2  (AIO_1_IN-TP30-NTC)
#define     CONNECT_TO_GPIO_2                       (0)                     // PA13 (12V_DET)
#define     CONNECT_TO_GPIO_3                       (GPIO_B | GPIO_Pin_15)  // PB15 (TP10 - SWCLK)
#define     CONNECT_TO_GPIO_4                       (GPIO_B | GPIO_Pin_14)  // PB14 (TP7  - SWDIO)
#define     CONNECT_TO_GPIO_5                       (GPIO_B | GPIO_Pin_10)  // PB10 (TP15 - CF)
#else
#define     CONNECT_TO_GPIO_1                       (GPIO_A | GPIO_Pin_2)   // PA2  (DOOR-TP28, DOOR-TP29)
#define     CONNECT_TO_GPIO_2                       (GPIO_A | GPIO_Pin_13)  // PA13 (SYS-TP27, SYS-TP30)
#define     CONNECT_TO_GPIO_3                       (GPIO_B | GPIO_Pin_15)  // PB15 (TP10 - SWCLK)
#define     CONNECT_TO_GPIO_4                       (GPIO_B | GPIO_Pin_14)  // PB14 (TP7  - SWDIO)
#define     CONNECT_TO_GPIO_5                       (GPIO_B | GPIO_Pin_10)  // PB10 (TP15 - UD-)
#endif


/* 治具接线4: TP29 -> 10k -> GND || TP42 -> 10k -> GND */
// 无


// FA Strings
#define     BOOT_MODE_SA                            "SA"
#define     BOOT_MODE_FA                            "FA"
#define     KEY_DOWN_STR                            "  "
#define     SENSOR_E2_STR                           "E2"
#define     SENSOR_E3_STR                           "E3"
#define     UPLOAD_FAIL_STR                         "FF"

#ifdef FA_LED_BANK_TEST
#define     LED_FA_KEY_STR                          "51"
#define     LED_FA_OK_STR                           "66"
#endif


// 其他定义
#define     SEND_TO_MASTER                          UART1_SendString
#define     SEND_TO_SLAVE                           UART0_SendString

#define     SEND_RESPONSE(cmd, buf, len)            ftm_pkt_send(1, cmd, buf, len)
#define     SEND_RESULT(cmd, value)                 do {                                                                                                            \
                                                            int result = (int)value;                                                                                \
                                                            uint8_t buf = (result < 0)? (NOT_SUPPORT) : (result > 0 ? OK : FAIL);                                   \
                                                            SEND_RESPONSE(cmd, &buf, sizeof(buf));                                                                  \
                                                    } while (0)


/* command define */
#define     FTM_MASTER_CMD_PREFIX                   (0x8000)

#define     FTM_SN                                  (0x8101)      // 设置/查询SN
#define     FTM_HW                                  (0x8102)      // 查询硬件版本号
#define     FTM_SW                                  (0x8103)      // 查询软件版本号
#define     FTM_BT_UUID                             (0x8104)      // 设置/查询BT UUID
#define     FTM_BOOTMODE                            (0x8105)      // 设置/查询boot mode (M0本身)
#define     FTM_DEVICE_ID                           (0x8106)      // 设置/查询deviceId
#define     FTM_RELAY_1                             (0x8107)      // 继电器(压机) & 门开关
#define     FTM_ZHAOMING                            (0x8108)      // 照明(接到其他某个IO口上测试)
#define     FTM_LENGNING                            (0x8109)      // 冷凝(接到其他某个IO口上测试)
#define     FTM_ZHENGFA                             (0x810A)      // 蒸发(接到其他某个IO口上测试)
#define     FTM_POWER_METER                         (0x810B)      // 校准功率计(继电器1接220V负载)
#define     FTM_IRDA                                (0x810C)      // 红外
#define     FTM_BEEP                                (0x8133)      // 蜂鸣器
#define     FTM_NTC_1                               (0x8134)      // 测试温度传感器-1
#define     FTM_NTC_2                               (0x8135)      // 测试温度传感器-2
#define     FTM_RELAY_2                             (0x8141)      // 继电器(风机) & 系统开关
#define     FTM_RELAY_3                             (0x8142)      // 继电器(xx) & yy开关
#define     FTM_RELAY_4                             (0x8144)      // 继电器(xx) & yy开关
#define     FTM_485_TEST                            (0x8143)      // PC发送给M0的, 检查485通路
#define     FTM_COM_TEST                            (0x8200)      // 测试M0的对外串口

#define     FTM_SLAVE_CMD_PREFIX                    (0x9000)
#define     CAT1_QUERY_M0_INFO                      (0x0001)      // Cat1发给M0的业务包
#define     FTM_SET_SLAVE_TO_WK                     (0x9106)      // M0在SA模式下, 通过按键5次(而不是通常的发命令的方式)可以设置Cat1到Work模式
#define     FTM_WIFI_BT_MAC                         (0x910B)      // PC获取bt/wifi地址, 有些项目蓝牙是在M0端
#define     FTM_PLAY_MP3                            (0x9135)
#define     FTM_M0_REPORT_FA_RESULT                 (0x9300)      // M0的FA是否测试完成上报给Cat1

#if HAS_UUID
#include    "CH58xBLE_LIB.H"
#endif
#if HAS_POWER_METER
#include    "hal_pow_meter.h"
#endif


/* packet 头固定格式 */
#define     PKT_PREFIX                              { 0xAA, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
#define     PKT_SUFFIX                              (0xBB)
#define     PKT_HEAD_SZ                             (8/*sizeof(PKT_PREFIX)*/ + 2 /* cmd(0xaabb) */ + 1 /* data_len(0xcc) */)

#define     RSP_NOT_SET                             (0xFF)

#define     RECV_BUF_SIZE                           (1 * 1024)


/* NV default */
#if 1
#define     DEFAULT_SN_DEVICE_ID_VAL                "NA1234567890"
#define     BLE_UUID_DEFAULT                        { 0xAB, 0x81, 0x90, 0xD5, 0xD1, 0x1E, 0x49, 0x41, 0xAC, 0xC4, 0x42, 0xF3, 0x05, 0x10, 0xB4, 0x08 }
#define     BLE_MAJOR_DEFAULT                       0xFFFF
#define     BLE_MINOR_DEFAULT                       0xFFFF

#define     DEVINFO_NV_PATH                         (0x00000000 + EEPROM_PAGE_SIZE * 0)
#define     DEVINFO_NV_FLAG                         0x11223344
#endif

/* M0 mode */
enum {
  MODE_LP = 0,
  MODE_SA,
  MODE_FA,
  MODE_WK,
};

/* packet command type */
enum {
  CMD_NONE = 0,
  CMD_GET,                                          /* read */
  CMD_SET,                                          /* write */
};

/* FA 测试步骤 */
enum {
  FA_STEP_NONE = 0,

  /* 继电器1-n, 包含again */
  FA_STEP_RELAY_START,
  FA_STEP_RELAY_END = FA_STEP_RELAY_START + RELAY_NUM * 2 - 1,

  /* mp3播放, 3次 */
#if HAS_MP3
  FA_STEP_MP3_START,
  FA_STEP_MP3_END = FA_STEP_MP3_START + MP3_NUM * 2 - 1,
#endif

  /* 数码灯管 */
#if HAS_LAMP
  FA_STEP_LAMP,
#endif

  /* 按键 */
#if HAS_LAMP            
  FA_STEP_KEY_START = ZQ_KEY_NUM ? (FA_STEP_LAMP + 1) : FA_STEP_LAMP,
#else
  FA_STEP_KEY_START = ZQ_KEY_NUM ? (FA_STEP_RELAY_END + 1) : FA_STEP_RELAY_END,
#endif
  FA_STEP_KEY_END = ZQ_KEY_NUM ? (FA_STEP_KEY_START + ZQ_KEY_NUM * 2 - 1) : FA_STEP_KEY_START,

  /* LED IO */
#if HAS_IO_LED
  FA_STEP_LED_START,
  FA_STEP_LED_END = FA_STEP_LED_START + 3 * 2 - 1,
#endif

  /* 门开关-1 */
#if HAS_DOOR_1
  FA_STEP_DOOR_1_START,
  FA_STEP_DOOR_1_END,
#endif

  /* 门开关-2 */
#if HAS_DOOR_2
  FA_STEP_DOOR_2_START,
  FA_STEP_DOOR_2_END,
#endif

  /* 系统开关 */
#if HAS_SYS
  FA_STEP_SYS_START,
  FA_STEP_SYS_END,
#endif

  /* 温度传感器-1 */
#if HAS_NTC_1
  FA_STEP_NTC_1_START,
  FA_STEP_NTC_1_END,
#endif

  /* 温度传感器-2 */
#if HAS_NTC_2
  FA_STEP_NTC_2_START,
  FA_STEP_NTC_2_END,
#endif

  /* 温度传感器-3 - LED电流检测 */
#if HAS_NTC_3
  FA_STEP_NTC_3_START,
  FA_STEP_NTC_3_END,
#endif

  /* 红外传感器 */
#if HAS_IRDA
  FA_STEP_IRDA_START,
  FA_STEP_IRDA_END,
#endif

  /* 对外串口 */
#if HAS_COM
  FA_STEP_COM_START,
  FA_STEP_COM_END,
#endif


  /* 定义FA最后一项 */
#if HAS_COM
  FA_STEP_COMPLETE = FA_STEP_COM_END,
#elif HAS_IRDA
  FA_STEP_COMPLETE = FA_STEP_IRDA_END,
#elif HAS_NTC_3
  FA_STEP_COMPLETE = FA_STEP_NTC_3_END,
#elif HAS_NTC_2
  FA_STEP_COMPLETE = FA_STEP_NTC_2_END,
#elif HAS_NTC_1
  FA_STEP_COMPLETE = FA_STEP_NTC_1_END,
#elif HAS_SYS
  FA_STEP_COMPLETE = FA_STEP_SYS_END,
#elif HAS_DOOR_2
  FA_STEP_COMPLETE = FA_STEP_DOOR_2_END,
#elif HAS_DOOR_1
  FA_STEP_COMPLETE = FA_STEP_DOOR_1_END,
#elif HAS_IO_LED
  FA_STEP_COMPLETE = FA_STEP_LED_END,
#else
  FA_STEP_COMPLETE = FA_STEP_KEY_END,
#endif

  FA_STEP_STOP
};

/* FA 测试结果 */
enum {
  FA_TESTING = 0,                                   /* 测试中 */
  FA_TEST_OK,                                       /* 测试完成 */
  FA_UPLOAD_OK,                                     /* 上传服务器完成 */
};

/* packet struction */
typedef struct {
  uint16_t cmd;                                     /* 命令ID */
  uint8_t* data;                                    /* 数据内容 */
  uint32_t data_len;                                /* 数据长度 */
  uint8_t sum;                                      /* check sum */
  uint8_t len;                                      /* 整个有效包的长度 */
} pkt_t;

typedef struct {
  int32_t  bootmode;                                // 01:SA, 02:FA, 03:WK

  uint8_t  sn[32];
  uint8_t  sn_len;

  uint8_t  did[32];
  uint8_t  did_len;

  /* M0也有机会要保存这3个值的 */
  uint8_t  ble_uuid[16];
  uint16_t ble_major;
  uint16_t ble_minor;

  uint32_t flag;

  // note: 新加参数要放到最后, flag的后面 ！
#if HAS_POWER_METER
  /* 功率计校准-电压&电流&功率 */
  int8_t   vol_ratio_delta;   // 0 - 100 (%)
  int8_t   cur_ratio_delta;   // 0 - 100 (%)
  int8_t   pow_ratio_delta;   // 0 - 100 (%)
#endif
} devinfo_t;

/* import functions */
extern uint8_t DrvReadKeys(void);
extern short GetMeasureTem(void);

/* export functions */
extern bool ftm_bootmode_write(uint8_t bootmode, bool reboot);
extern void ftm_start(void);

void process_uart_pc(void);
void process_uart_cat1(void);

#endif  // _FTM_H_
